/* image.h */

#ifndef DODO_IMAGE_H
#define DODO_IMAGE_H

#include <dodo_plot/kernel/plotfwd.h>
#include <dodo_plot/kernel/color.h>
#include <dodo_plot/kernel/position.h>
#include <dodo_plot/kernel/colormap.h>
#include <vector>

namespace dodo_plot
{

inline unsigned char float_to_byte(double in)
{
	return (unsigned char)(in * 255 + 0.5);
}

class Image_Body;

/**
 * 将图像数据矩阵转化为实际图像.
 * 原始数据可以为1个灰度矩阵或3个分别代表RGB值的矩阵.
 * 构造函数中的数据类型T为指向矩阵开始的迭代器(即可以为原始指针). 
 * 对于灰度矩阵, 内容可以为与Colormap对应的下标值, 或任意类型数据(此时需提供一个转换函数).
 * 对于3个RGB矩阵, 内容为RGB值
 * (如果数据类型为int或unsigned char, 则范围为0 ~ 255, 否则为0.0 ~ 1.0), 
 * 或任意类型(此时需提供一个转换函数). 
 *
 * 如果图像需做旋转, 则可用rotate_0(), rotate_90(), rotate_180(), rotate_270()等接口.
 * 图像翻转尚未实现.
 */
/// 将图像数据矩阵转化为实际图像
class Image
{
public:
	void draw(const Plotter& plotter) const;
	double width() const;
	double height() const;
	Position local_pos() const;

public:
	void rotate_0();
	void rotate_90();
	void rotate_180();
	void rotate_270();
	/// 尚未实现
	void flip_lr();
	/// 尚未实现
	void flip_ud();

	// for gray scale pictures
	/// 数据应与Colormap的下标值对应.
	template<class T>
	Image(int w, int h,
		T image,
		const Colormap& colormap,
		bool is_grid_image = false);

	/// 数据可为任意类型, 由converter转换为Colormap的下标. 
	template<class T, class Convert>
	Image(int w, int h, 
		T image, 
		const Colormap& colormap,
		const Convert& converter, 
		bool is_grid_image = false);

	// for r g b pictures.
	/// 数据类型若为int或unsigned char, 则范围为0 ~ 255; 
	/// 否则为0.0 ~ 1.0; (long等其他整数类型小心, 建议用带转换函数的版本).
	template<class T>
	Image(int w, int h,
		T r, T g, T b, 
		bool is_grid_image = false);
	///由converter将原始数据转换为{int/unsigned char}或{double/float}型.
	/// 前者范围为0 ~ 255, 后者范围为0.0 ~ 1.0. 
	template<class T, class Convert>
	Image(int w, int h, 
		T r, T g, T b, 
		const Convert& converter, 
		bool is_grid_image = false);

	Image(const Image& orig);
	~Image();
	Image& operator=(const Image& orig);

private:
	Image_Body* body_;
};

class Image_Body
{
	friend class Image;
private:
	enum Rotate_Mode
	{
		NO_ROTATE,
		ROTATE_90,
		ROTATE_180,
		ROTATE_270
	};
	enum Flip_Mode
	{
		NO_FLIP,
		FLIP_LR
	};
private:
	void draw(const Plotter& plotter) const;
	int width() const; 
	int height() const; 
	Position local_pos() const;

	void push_back(const Color& c);
	void set_rotate(Image_Body::Rotate_Mode mode);
	void set_flip(Image_Body::Flip_Mode flip);

private:
	Image_Body(int w, int h, bool is_grid_image);
	~Image_Body();
private:
	int use_count_;

	int stride_;
	int current_col_;
	int pad_byte_count_;

	int w_, h_;
	
	unsigned char* value_; //data;
	unsigned char* p_;	//pos_pointer;

	int filter_mode_;


	Rotate_Mode rotate_mode_;
	Flip_Mode flip_mode_;
};

}

#include <dodo_plot/widget/image.tcc>

#endif //DODO_IMAGE_H

